package SGNet

import (
	"encoding/binary"
	"io"
	log "misc/seelog"
	"net"
	"strings"
	"time"
	cfg "utils/config"
)

const (
	INQUEUE_SIZE = 64
	TCP_TIMEOUT  = 60
	MAX_DELAY_IN = 60
)

type ServerHandlerFunc func(*Message)

const (
	MESSAGETYPE_CLIENT = 0
	MESSAGETYPE_CMD    = 1
)

type Message struct {
	Type  uint8
	Sess  *Session
	Id    uint16
	Data  []byte
	Param map[string]interface{}
}

func Run() {

	port := ":" + cfg.Get()["port"]
	tcpAddr, err := net.ResolveTCPAddr("tcp4", port)
	if err != nil {
		log.Info(err)
	}
	listener, err := net.ListenTCP("tcp", tcpAddr)
	if err != nil {
		log.Info(err)
	}
	log.Info("GameServer Start " + tcpAddr.String())

	for {
		conn, err := listener.Accept()
		if err != nil {
			log.Info("accept failed", err)
			continue
		}
		go handleClient(conn)
	}
}

var ClientLostMessage func(*Session)

func handleClient(conn net.Conn) {

	var sess Session
	sess.IP = net.ParseIP(strings.Split(conn.RemoteAddr().String(), ":")[0])
	sess.Conn = conn
	sess.keepAliveTime = int64(time.Second * 60)
	sess.in = make(chan []byte, INQUEUE_SIZE)
	sess.out = make(chan []byte, INQUEUE_SIZE)
	sess.InMessageQueue = make(chan Message, INQUEUE_SIZE)
	log.Info("new connection from" + sess.IP.String())
	defer func() {
		sess.Close()
	}()
	header := make([]byte, 4)
	go startAgent(&sess)
	for {
		//设置读取超时时间 超过这个时间客户端没有发来数据  Io.ReadFull这会出错退出本函数
		//退出时调用 defer close(in) Agent读取会失败 Agent也会结束.
		conn.SetReadDeadline(time.Now().Add(TCP_TIMEOUT * time.Second))
		//header
		n, err := io.ReadFull(conn, header)

		if err != nil {
			log.Info("Read Head Error ", err, n)
			break
		}
		//data
		size := binary.BigEndian.Uint32(header)
		//!!如果size的大小大于实际数据大小 conn会一直等待数据直到超时之前不会报错.
		data := make([]byte, size)
		n, err = io.ReadFull(conn, data)
		if err != nil {
			log.Info("ReadDataErr ", err)
			break
		}
		select {
		case sess.in <- data:
		case <-time.After(MAX_DELAY_IN * time.Second):
			log.Warn("server busy or agent closed")
			return

		}
	}

}
